// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include <zencore/except.h>
#include <zencore/zencore.h>

ZEN_THIRD_PARTY_INCLUDES_START
#include <cxxopts.hpp>
ZEN_THIRD_PARTY_INCLUDES_END

namespace cpr {
class Response;
}

namespace zen {

struct ZenCliOptions
{
	bool IsDebug   = false;
	bool IsVerbose = false;

	// Arguments after " -- " on command line are passed through and not parsed
	std::string				 PassthroughCommandLine;
	std::string				 PassthroughArgs;
	std::vector<std::string> PassthroughArgV;
};

struct ZenCmdCategory
{
	std::string						   Name;
	std::map<std::string, std::string> SortedCmds;
};

extern ZenCmdCategory g_UtilitiesCategory;
extern ZenCmdCategory g_ProjectStoreCategory;
extern ZenCmdCategory g_CacheStoreCategory;
extern ZenCmdCategory g_StorageCategory;

/** Base class for command implementations
 */

class ZenCmdBase
{
public:
	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) = 0;
	virtual cxxopts::Options& Options()														 = 0;
	virtual ZenCmdCategory&	  CommandCategory() const;

	bool			   ParseOptions(int argc, char** argv);
	static bool		   ParseOptions(cxxopts::Options& Options, int argc, char** argv);
	static int		   GetSubCommand(cxxopts::Options&			  Options,
									 int						  argc,
									 char**						  argv,
									 std::span<cxxopts::Options*> SubOptions,
									 cxxopts::Options*&			  OutSubOption,
									 std::vector<char*>&		  OutSubCommandArguments);
	static std::string FormatHttpResponse(const cpr::Response& Response);
	static int		   MapHttpToCommandReturnCode(const cpr::Response& Response);
	static std::string ResolveTargetHostSpec(const std::string& InHostSpec);
	static std::string ResolveTargetHostSpec(const std::string& InHostSpec, uint16_t& OutEffectivePort);
};

class StorageCommand : public ZenCmdBase
{
	virtual ZenCmdCategory& CommandCategory() const override { return g_StorageCategory; }
};

class CacheStoreCommand : public ZenCmdBase
{
	virtual ZenCmdCategory& CommandCategory() const override { return g_CacheStoreCategory; }
};

}  // namespace zen
